<?php

/**
 * 提供一些公用的函数，供控制器调用
 *
 */
class Hm_Util
{
    protected $_app_path;

    function __construct ($path)
    {
        if(realpath($path)){
            $this->_app_path = $path;
            return ;
        }
        throw new Exception('提供的程序地址非法！');
    }

    static public function getip ()
    {
        if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
            $ip = getenv('HTTP_CLIENT_IP');
        } else
            if (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
                $ip = getenv('HTTP_X_FORWARDED_FOR');
            } else
                if (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
                    $ip = getenv('REMOTE_ADDR');
                } else
                    if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
                        $ip = $_SERVER['REMOTE_ADDR'];
                    }
        $temp = array();
        preg_match("/[\d\.]{7,15}/", $ip, $temp);
        $ip = $temp[0] ? $temp[0] : 'unknown';
        unset($temp);
        return $ip;
    }

    static public function convertip ($ip)
    {
        $return = '';
        if (preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {
            $iparray = explode('.', $ip);
            if ($iparray[0] == 10 || $iparray[0] == 127 || ($iparray[0] == 192 && $iparray[1] == 168) || ($iparray[0] == 172 && ($iparray[1] >= 16 && $iparray[1] <= 31))) {
                $return = '- LAN';
            } elseif ($iparray[0] > 255 || $iparray[1] > 255 || $iparray[2] > 255 || $iparray[3] > 255) {
                $return = '- Invalid IP Address';
            } else {
                $tinyipfile = APPLICATION_PATH . '/data/ipdata/tinyipdata.dat';
                $fullipfile = APPLICATION_PATH . '/data/ipdata/wry.dat';
                if (@file_exists($fullipfile)) {
                    $return = self::convertip_full($ip, $fullipfile);
                }elseif (@file_exists($tinyipfile)){
                    $return = self::convertip_tiny($ip, $tinyipfile);
                }
            }
        }
        return $return;
    }

    static public function convertip_tiny ($ip, $ipdatafile)
    {
        static $fp = NULL, $offset = array(), $index = NULL;
        $ipdot = explode('.', $ip);
        $ip = pack('N', ip2long($ip));
        $ipdot[0] = (int) $ipdot[0];
        $ipdot[1] = (int) $ipdot[1];
        if ($fp === NULL && $fp = @fopen($ipdatafile, 'rb')) {
            $offset = unpack('Nlen', fread($fp, 4));
            $index = fread($fp, $offset['len'] - 4);
        } elseif ($fp == FALSE) {
            return '- Invalid IP data file';
        }
        $length = $offset['len'] - 1028;
        $start = unpack('Vlen', $index[$ipdot[0] * 4] . $index[$ipdot[0] * 4 + 1] . $index[$ipdot[0] * 4 + 2] . $index[$ipdot[0] * 4 + 3]);
        for ($start = $start['len'] * 8 + 1024; $start < $length; $start += 8) {
            if ($index{$start} . $index{$start + 1} . $index{$start + 2} . $index{$start + 3} >= $ip) {
                $index_offset = unpack('Vlen', $index{$start + 4} . $index{$start + 5} . $index{$start + 6} . "\x0");
                $index_length = unpack('Clen', $index{$start + 7});
                break;
            }
        }
        fseek($fp, $offset['len'] + $index_offset['len'] - 1024);
        if ($index_length['len']) {
            return '- ' . fread($fp, $index_length['len']);
        } else {
            return '- Unknown';
        }
    }

    static public function convertip_full ($ip, $ipdatafile)
    {
        if (! $fd = @fopen($ipdatafile, 'rb')) {
            return '- Invalid IP data file';
        }
        $ip = explode('.', $ip);
        $ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
        if (! ($DataBegin = fread($fd, 4)) || ! ($DataEnd = fread($fd, 4)))
            return;
        @$ipbegin = implode('', unpack('L', $DataBegin));
        if ($ipbegin < 0)
            $ipbegin += pow(2, 32);
        @$ipend = implode('', unpack('L', $DataEnd));
        if ($ipend < 0)
            $ipend += pow(2, 32);
        $ipAllNum = ($ipend - $ipbegin) / 7 + 1;
        $BeginNum = $ip2num = $ip1num = 0;
        $ipAddr1 = $ipAddr2 = '';
        $EndNum = $ipAllNum;
        while ($ip1num > $ipNum || $ip2num < $ipNum) {
            $Middle = intval(($EndNum + $BeginNum) / 2);
            fseek($fd, $ipbegin + 7 * $Middle);
            $ipData1 = fread($fd, 4);
            if (strlen($ipData1) < 4) {
                fclose($fd);
                return '- System Error';
            }
            $ip1num = implode('', unpack('L', $ipData1));
            if ($ip1num < 0)
                $ip1num += pow(2, 32);
            if ($ip1num > $ipNum) {
                $EndNum = $Middle;
                continue;
            }
            $DataSeek = fread($fd, 3);
            if (strlen($DataSeek) < 3) {
                fclose($fd);
                return '- System Error';
            }
            $DataSeek = implode('', unpack('L', $DataSeek . chr(0)));
            fseek($fd, $DataSeek);
            $ipData2 = fread($fd, 4);
            if (strlen($ipData2) < 4) {
                fclose($fd);
                return '- System Error';
            }
            $ip2num = implode('', unpack('L', $ipData2));
            if ($ip2num < 0)
                $ip2num += pow(2, 32);
            if ($ip2num < $ipNum) {
                if ($Middle == $BeginNum) {
                    fclose($fd);
                    return '- Unknown';
                }
                $BeginNum = $Middle;
            }
        }
        $ipFlag = fread($fd, 1);
        if ($ipFlag == chr(1)) {
            $ipSeek = fread($fd, 3);
            if (strlen($ipSeek) < 3) {
                fclose($fd);
                return '- System Error';
            }
            $ipSeek = implode('', unpack('L', $ipSeek . chr(0)));
            fseek($fd, $ipSeek);
            $ipFlag = fread($fd, 1);
        }
        if ($ipFlag == chr(2)) {
            $AddrSeek = fread($fd, 3);
            if (strlen($AddrSeek) < 3) {
                fclose($fd);
                return '- System Error';
            }
            $ipFlag = fread($fd, 1);
            if ($ipFlag == chr(2)) {
                $AddrSeek2 = fread($fd, 3);
                if (strlen($AddrSeek2) < 3) {
                    fclose($fd);
                    return '- System Error';
                }
                $AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
                fseek($fd, $AddrSeek2);
            } else {
                fseek($fd, - 1, SEEK_CUR);
            }
            while (($char = fread($fd, 1)) != chr(0))
                $ipAddr2 .= $char;
            $AddrSeek = implode('', unpack('L', $AddrSeek . chr(0)));
            fseek($fd, $AddrSeek);
            while (($char = fread($fd, 1)) != chr(0))
                $ipAddr1 .= $char;
        } else {
            fseek($fd, - 1, SEEK_CUR);
            while (($char = fread($fd, 1)) != chr(0))
                $ipAddr1 .= $char;
            $ipFlag = fread($fd, 1);
            if ($ipFlag == chr(2)) {
                $AddrSeek2 = fread($fd, 3);
                if (strlen($AddrSeek2) < 3) {
                    fclose($fd);
                    return '- System Error';
                }
                $AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
                fseek($fd, $AddrSeek2);
            } else {
                fseek($fd, - 1, SEEK_CUR);
            }
            while (($char = fread($fd, 1)) != chr(0))
                $ipAddr2 .= $char;
        }
        fclose($fd);
        if (preg_match('/http/i', $ipAddr2)) {
            $ipAddr2 = '';
        }
        $ipaddr = "$ipAddr1 $ipAddr2";
        $ipaddr = preg_replace('/CZ88\.NET/is', '', $ipaddr);
        $ipaddr = preg_replace('/^\s*/is', '', $ipaddr);
        $ipaddr = preg_replace('/\s*$/is', '', $ipaddr);
        if (preg_match('/http/i', $ipaddr) || $ipaddr == '') {
            $ipaddr = '- Unknown';
        }
        return '- ' . $ipaddr;
    }

    static public function mk_dir ($dir, $mode = 0755)
    {
        if (file_exists($dir))
            return false;
        if (is_dir($dir) || @mkdir($dir, $mode))
            return true;
        if (! self::mk_dir(dirname($dir), $mode))
            return false;
        return @mkdir($dir, $mode);
    }

    /**
     * 创建多级目录。
     *
     * @param string $path  目标路径
     * @return 成功或失败
     */
    static function createDir ($path)
    {
        $path = str_replace('\\', '/', $path);
        if (is_dir($path))
            return true;
        if (file_exists($path))
            return false;
        $parent = substr($path, 0, strrpos($path, '/'));
        if ($parent === '' || $parent === '.' || self::createDir($parent))
            return @mkdir($path); //      #    没权限的
        else
            return false;
    }

    static public function empty_dir ($directory)
    {
        $handle = opendir($directory);
        while (($file = readdir($handle)) !== false) {
            if ($file != "." && $file != "..") {
                closedir($handle);
                return false;
            }
        }
        closedir($handle);
        return true;
    }

    static public function hsetcookie ($var, $value, $life = 0)
    {
        setcookie($var, $value, $life ? $this->time + $life : 0);
    }

    /**
     * 可逆加密解密函数
     *
     * @param unknown_type $string
     * @param unknown_type $action
     * @return unknown
     */
    static function StrCode ($string, $action = 'ENCODE', $hash = 'This is Hmcms.')
    {
        $action != 'ENCODE' && $string = base64_decode($string);
        $code = '';
        $HTTP_USER_AGENT = str_replace(array(
            '<' ,
            '>' ,
            '"' ,
            "'" ,
            '%3C' ,
            '%3E' ,
            '%22' ,
            '%27' ,
            '%3c' ,
            '%3e'
        ), '', $_SERVER['HTTP_USER_AGENT']);
        $key = substr(md5($HTTP_USER_AGENT . $hash), 8, 18);
        $keylen = strlen($key);
        $strlen = strlen($string);
        for ($i = 0; $i < $strlen; $i ++) {
            $k = $i % $keylen;
            $code .= $string[$i] ^ $key[$k];
        }
        return ($action != 'DECODE' ? base64_encode($code) : $code);
    }

    /**
     * 可逆加密解密函数，去掉USER_AGENT
     *
     * @param unknown_type $string
     * @param unknown_type $action
     * @return unknown
     */
    static function StrCodeEasy ($string, $action = 'ENCODE', $hash = 'This is Hmcms.')
    {
        $action != 'ENCODE' && $string = base64_decode($string);
        $code = '';
        $key = substr(md5($hash), 8, 18);
        $keylen = strlen($key);
        $strlen = strlen($string);
        for ($i = 0; $i < $strlen; $i ++) {
            $k = $i % $keylen;
            $code .= $string[$i] ^ $key[$k];
        }
        return ($action != 'DECODE' ? base64_encode($code) : $code);
    }

    /**
     * 对字符串或数组进行格式化，返回格式化后的数组
     *
     * $input 参数如果是字符串，则首先以“,”为分隔符，将字符串转换为一个数组。
     * 接下来对数组中每一个项目使用 trim() 方法去掉首尾的空白字符。最后过滤掉空字符串项目。
     *
     * 该方法的主要用途是将诸如：“item1, item2, item3” 这样的字符串转换为数组。

     * @param array|string $input 要格式化的字符串或数组
     * @param string $delimiter 按照什么字符进行分割
     *
     * @return array 格式化结果
     */
    static function normalize ($input, $delimiter = ',')
    {
        if (! is_array($input)) {
            $input = explode($delimiter, $input);
        }
        $input = array_map('trim', $input);
        return array_filter($input, 'strlen');
    }

    /**
     * 字符截取，支持utf-8及中文
     */
	static public function cutstr($string,$start, $length,$charset='utf-8', $dot = ' ...') {
		if(strlen($string) <= $length) {
			return $string;
		}
		$string = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;'), array('&', '"', '<', '>'), $string);
		$strcut = '';
		if(strtolower($charset) == 'utf-8') {
			$n = $tn = $noc = 0;
			while($n < strlen($string)) {
				$t = ord($string[$n]);
				if($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
					$tn = 1; $n++; $noc++;
				} elseif(194 <= $t && $t <= 223) {
					$tn = 2; $n += 2; $noc += 2;
				} elseif(224 <= $t && $t < 239) {
					$tn = 3; $n += 3; $noc += 2;
				} elseif(240 <= $t && $t <= 247) {
					$tn = 4; $n += 4; $noc += 2;
				} elseif(248 <= $t && $t <= 251) {
					$tn = 5; $n += 5; $noc += 2;
				} elseif($t == 252 || $t == 253) {
					$tn = 6; $n += 6; $noc += 2;
				} else {
					$n++;
				}
				if($noc >= $length) {
					break;
				}
			}
			if($noc > $length) {
				$n -= $tn;
			}
			$strcut = substr($string, $start, $n);
		} else {
			for($i = 0; $i < $length; $i++) {
				$strcut .= ord($string[$i]) > 127 ? $string[$i].$string[++$i] : $string[$i];
			}
		}
		$strcut = str_replace(array('&', '"', '<', '>'), array('&amp;', '&quot;', '&lt;', '&gt;'), $strcut);
		return $strcut.$dot;
	}

	/**
	 * 删除非站内链接
	 */
	static function deleteLink($string)
	{
		$basehost = "http://".$_SERVER['HTTP_HOST'];
		$string = str_replace($basehost,'#basehost#',$string);
		$string = preg_replace("/(<a\s+href=([^(http)]*)http:\/\/[^\/]([^>]*)>)(.*)(<\/a>)/isU","$4",$string);
		$string = str_replace('#basehost#',$basehost,$string);
		return $string;
	}

	/**
	 * 本地化远程图片
	 */
	public function localizeImage($body,$uploaddir)
	{
	    $httpDown = new Hm_Httpdown();
	    $basehost = "http://".$_SERVER["HTTP_HOST"];
	    $img_array = array();
	    preg_match_all("/src\s?=[^(http)]*(http:\/\/([^>]*)\.(gif|jpg|png))/isU",$body,$img_array);
	    $img_array = array_unique($img_array[1]);
	    $imgUrl  = rtrim($uploaddir,'\/').'/'.date('Y/m/');
	    $imgPath = $this->_app_path . $imgUrl;
	    if(!is_dir($imgPath)){
	        self::createDir($imgPath);
	    }
	    foreach($img_array as $key=>$value){
	        if(eregi($basehost,$value)){
	            continue;
	        }
	        if(!eregi("^http://",$value)){
		        continue;
		    }
		    $httpDown->OpenUrl($value);
		    $itype = $httpDown->GetHead("content-type");
		    $type = substr($value,-4,4);
		    if(!eregi("\.(jpg|gif|png)",$type)){
		        if($itype=='image/gif'){
		            $type = ".gif";
		        }else if($itype=='image/png'){
		            $type = ".png";
		        }else{
		            $type = '.jpg';
		        }
		    }
		    $rnd = mt_rand(1000,9000);
		    $value = trim($value);
		    $rndFileName = $imgPath.$rnd.'_'.$key.$type;
		    $fileurl = $imgUrl.$rnd.'_'.$key.$type;
		    $rs = $httpDown->SaveToBin($rndFileName);
		    if($rs){
		        $body = str_replace($value,$fileurl,$body);
		    }
	    }
	    $httpDown->Close();
	    return $body;
	}


	/**
	 * 取第一个图片为缩略图
	 */
	public function firstImgAsThumb(&$body,$toWidth=150,$toHeight=200,$uploaddir='')
	{
    	$litpic = '';
    	$img_array = array();
    	preg_match_all("/(src)=[\"|'|\s]{0,}([^>]*\.(gif|jpg|bmp|png))/isU",$body,$img_array);
    	$img_array = array_unique($img_array[2]);
    	if(count($img_array)>0){
    		$picname = preg_replace("/[\"|'|\s]{1,}/", '', $img_array[0]);
    		if(ereg("_lit\.",$picname)){
    			$litpic = $picname;
    		}else{
    			$litpic = $this->makeImgThumb($picname,$toWidth,$toHeight,$uploaddir);
    		}
    	}
    	return $litpic;
	}

    /**
     * 获得缩略图,可以对远程图片进行操作
     *
     * @param unknown_type $litpic
     * @param unknown_type $picname
     * @param unknown_type $uploaddir
     * @param unknown_type $appDir
     * @param unknown_type $isremote
     * @return unknown
     */
    public function makeImgThumb($picname,$toWidth=150,$toHeight=200,$uploaddir='')
    {
		$picname = trim($picname);
		$basehost = "http://".$_SERVER['HTTP_HOST'];
		if(eregi("^http://",$picname)&&!eregi($basehost,$picname)){
			$image = $this->downloadImage($picname,$uploaddir);
			if(!$image){
				$litpic = '';
			}else{
				$oldpic = $this->_app_path.$picname;
				$litpic = str_replace('.','-lp.',$picname);
				@$this->ImageResize($oldpic,$toWidth,$toHeight,$this->_app_path.$litpic);
				if(!is_file($this->_app_path.$litpic)) $litpic = '';
			}
		}else{
			if(!eregi("^http://",$picname)){
				$oldpic = $this->_app_path.$picname;
				$litpic = str_replace('.','-lp.',$picname);
				@$this->ImageResize($oldpic,$toWidth,$toHeight,$this->_app_path.$litpic);
				if(!is_file($this->_app_path.$litpic)) $litpic = '';
			}else{
				$litpic = $picname;
				return $litpic;
			}
		}
    	return $litpic;
    }

    /**
     * 缩图片自动生成函数，来源支持bmp、gif、jpg、png
     * 但生成的小图只用jpg或png格式
     *
     * @param unknown_type $srcFile
     * @param unknown_type $toW
     * @param unknown_type $toH
     * @param unknown_type $toFile
     * @return unknown
     */
    public function ImageResize($srcFile,$toW,$toH,$toFile="")
    {
    	if($toFile=='') $toFile = $srcFile;
    	$info = '';
    	$srcInfo = getimagesize($srcFile,$info);
    	switch ($srcInfo[2]){
    		case 1:
    			$im = imagecreatefromgif($srcFile);
    			break;
    		case 2:
    			$im = imagecreatefromjpeg($srcFile);
    			break;
    		case 3:
    			$im = imagecreatefrompng($srcFile);
    			break;
    		case 6:
    			$im = imagecreatefromwbmp($srcFile);
    			break;
    	}
    	$srcW=ImageSX($im);
    	$srcH=ImageSY($im);
    	if($srcW<=$toW && $srcH<=$toH ){
    	    copy($srcFile,$toFile);
    	    return true;
    	}
    	$toWH=$toW/$toH;
    	$srcWH=$srcW/$srcH;
    	if($toWH<=$srcWH)
    	{
    		$ftoW=$toW;
    		$ftoH=$ftoW*($srcH/$srcW);
    	}
    	else
    	{
    		$ftoH=$toH;
    		$ftoW=$ftoH*($srcW/$srcH);
    	}
    	if($srcW>$toW||$srcH>$toH)
    	{
    		if(function_exists("imagecreatetruecolor"))
    		{
    			@$ni = imagecreatetruecolor($ftoW,$ftoH);
    			if($ni)
    			{
    				imagecopyresampled($ni,$im,0,0,0,0,$ftoW,$ftoH,$srcW,$srcH);
    			}
    			else
    			{
    				$ni=imagecreate($ftoW,$ftoH);
    				imagecopyresized($ni,$im,0,0,0,0,$ftoW,$ftoH,$srcW,$srcH);
    			}
    		}
    		else
    		{
    			$ni=imagecreate($ftoW,$ftoH);
    			imagecopyresized($ni,$im,0,0,0,0,$ftoW,$ftoH,$srcW,$srcH);
    		}
    		switch ($srcInfo[2])
    		{
    			case 1:
    				imagegif($ni,$toFile);
    				break;
    			case 2:
    				imagejpeg($ni,$toFile,100);
    				break;
    			case 3:
    				imagepng($ni,$toFile);
    				break;
    			case 6:
    				imagebmp($ni,$toFile);
    				break;
    			default:
    				return false;
    		}
    		imagedestroy($ni);
    	}
    	imagedestroy($im);
    	return true;
    }

    /**
     * 下载远程图片到本地上传目录
     */
    public function downloadImage($path,$uploaddir)
	{
	    $path = trim($path);
	    $httpDown = new Hm_Httpdown();
	    $basehost = "http://".$_SERVER["HTTP_HOST"];
	    $imgUrl  = rtrim($uploaddir,'\/').'/'.date('Y/m/');
	    $imgPath = $this->_app_path . $imgUrl;
	    if(!is_dir($imgPath)){
	        self::createDir($imgPath);
	    }
	    if(eregi("http://",$path)&&!eregi($basehost,$path)){
		    $httpDown->OpenUrl($path);
		    $itype = $httpDown->GetHead("content-type");
		    $type = substr($path,-4,4);
		    if(!eregi("\.(jpg|gif|png)",$type)){
		        if($itype=='image/gif'){
		            $type = ".gif";
		        }else if($itype=='image/png'){
		            $type = ".png";
		        }else{
		            $type = '.jpg';
		        }
		    }
		    $rnd = mt_rand(1000,9000);
		    $rnd2 = mt_rand(1000,9000);
		    $rndFileName = $imgPath.$rnd.'_'.$rnd2.$type;
		    $fileurl = $imgUrl.$rnd.'_'.$rnd2.$type;
		    $rs = $httpDown->SaveToBin($rndFileName);
		    $httpDown->Close();
		    if($rs){
		        return $fileurl;
		    }
	    }
	    return FALSE;
	}
	/**
	 * 验证用户数据
	 * 合法返回true，不合法返回字符串消息
	 */
	static public function validateUser(array $data)
	{
	    foreach ($data as $name=>$value){
    	    switch ($name){
                case 'username':
                    if(!$value){
                        return '请填写用户名';
                    }elseif(!Zend_Validate::is($value, 'StringLength', array(4, 20))){
                        return '用户名长度必须介于4到20之间';
                    }elseif(!Zend_Validate::is($value, 'Alnum')){
                        return '用户名只能由字母和数字组成';
                    }elseif(!Zend_Validate::is(substr($value,0,1), 'Alpha')){
                        return '用户名必须以字母开头';
                    }
                    break;
                case 'password':
                    if(!$value){
                        return '请填写密码';
                    }elseif(!Zend_Validate::is($value, 'StringLength', array(6, 32))){
                        return '密码长度必须介于6到32之间';
                    }
                    break;
                case 'realname':
                    if(!$value){
                        return '请填写真实姓名';
                    }elseif(!Zend_Validate::is($value, 'StringLength', array(2, 20))){
                        return '真实姓名填写不正确';
                    }
                    break;
                case 'gender':
                    if(!$value){
                        return '请选择您的性别';
                    }
                    break;
                case 'province':
                    if(!$value){
                        return '请选择您的地区';
                    }
                    break;
                case 'company_type':
                    if(!$value){
                        return '请选择您的公司类型';
                    }
                    break;
                case 'company_category':
                    if(!$value){
                        return '请选择您的公司所属行业';
                    }
                    break;
                case 'company_telephone':
                    if(!$value){
                        return '请填写您的公司电话';
                    }
                    break;
                case 'email':
                    if(!$value){
                        return '请填写Email地址';
                    }elseif(!Zend_Validate::is($value, 'EmailAddress')) {
                        return 'Email地址格式不正确';
                    }
                    break;
                case 'company_name':
                    if(!$value){
                        return '请填写公司名称';
                    }elseif(!Zend_Validate::is($value, 'StringLength', array(2, 30))){
                        return '公司名称长度必须介于2到30之间';
                    }
                    break;
                case 'captcha':
                    if ($_SESSION['AuthCode'] != md5($value)) {
                        return '验证码输入错误';
                    }
                    break;
                default:
                    ;
            }
	    }
	    return true;
	}
}